use std::collections::HashSet;

use swc_ecma_ast::*;  // 确保导入必要的AST类型
use swc_common::DUMMY_SP;
use swc_ecma_ast::{
    BinExpr, BinaryOp, BindingIdent, BlockStmt, BreakStmt, CallExpr, Callee, ComputedPropName, Decl, Expr,
    ExprOrSpread, ExprStmt, ForStmt, ForHead, ForOfStmt, Ident, IfStmt, Lit, MemberExpr, MemberProp, Number,
    Pat, ParenExpr, Stmt, Str, SwitchCase, SwitchStmt, TsAsExpr, TsEntityName, TsTypeAnn, TsType,
    TsKeywordType, TsKeywordTypeKind, TsTypeRef, TsTypeParamInstantiation, UpdateExpr, UpdateOp, VarDecl, VarDeclKind,
    VarDeclarator, VarDeclOrExpr,
};
use swc_ecma_utils::{quote_ident, quote_str};
use std::collections::HashMap;
use crate::context::PropPos;
use crate::{
    common::field,
    context::Context,
    descriptor::{self, OneofDescriptorProto, field_descriptor_proto::Type,},
    runtime::lark::protobuf_js::codec::host_field_accessor,
};

use super::{
    codec::{self, field_accesscor, FieldAccessor},
    common::{normalize_name, normalize_type_name},
    LarkPbRuntime,
};

impl LarkPbRuntime {
    pub(super) fn serialize_setup_inner(
        &self,
        ctx: &mut Context,
        descriptor: &descriptor::DescriptorProto,
        accessor: FieldAccessor,
    ) -> Vec<Stmt> {
        let mut stmts = vec![];
        stmts.push(self.serialize_setup_writer(ctx));
        // 跟踪处理过的 oneof 字段
        let mut oneofs = HashSet::new();
        // 源数据对象
        let host_expr = Expr::Ident(quote_ident!("$req"));

        for field in &descriptor.field {
             // 选择字段访问器（map 类型特殊处理）
            let field_accessor = if descriptor.options.map_entry() {
                accessor // 自定义访问器
            } else {
                host_field_accessor // 默认访问器
            };
            // 生成该字段的序列化代码
            let field_stmt = self.serialize_field_expr(//生成if语句中的内容
                ctx,
                host_expr.clone(),
                descriptor,
                field,
                field_accessor,
                &mut oneofs,
                None,
            );

            if let Some(stmt) = field_stmt {
                stmts.push(crate::if_stmt!(
                    // 检查字段是否有值
                    self.default_value_bin_expr( //构建if语句-判断条件-不包含内容
                        ctx,
                        host_expr.clone(),
                        descriptor,
                        field,
                        accessor
                    ),
                    Stmt::Block(BlockStmt {
                        span: DUMMY_SP,
                        stmts: vec![stmt]
                    })
                ));
            }
        }
        stmts.push(crate::return_stmt!(Expr::Ident(quote_ident!("$writer"))));
        stmts
    }

    pub(super) fn serialize_field_expr(
        &self,
        ctx: &mut Context,
        host_expr: Expr,
        descriptor: &descriptor::DescriptorProto,
        field: &descriptor::FieldDescriptorProto,
        field_accessor: FieldAccessor,
        oneofs: &mut HashSet<i32>,
        computed_prop: Option<bool>,
    ) -> Option<Stmt> {
        let has_computed_prop = computed_prop.unwrap_or(field.has_computed_prop());
        let field_accessor = if field.is_repeated() {
            codec::field_accesscor
        } else {
            field_accessor
        };
        let field_stmt: Stmt = if field.has_oneof_index() {
            eprintln!("[DEBUG] serialize.rs field >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}",field);
            if !oneofs.contains(&field.oneof_index()) {
                oneofs.insert(field.oneof_index());
                let oneof = descriptor
                    .oneof_decl
                    .get(field.oneof_index() as usize)
                    .unwrap();
                let mut fields = descriptor.get_oneof_fields(field);
                fields.push(field.clone());
                self.serialize_oneof_field_stmt(ctx, host_expr.clone(), oneof, &fields, descriptor)
            } else {
                return None;
            }
        } else if field.is_map(ctx) {
            self.serialize_map_field_stmt(ctx, host_expr.clone(), field)
        } else if field.is_message() {
            self.serialize_message_field_stmt(ctx, host_expr.clone(), field, field_accessor, computed_prop)
        } else {
            self.serialize_primitive_field_stmt(ctx, host_expr.clone(), field, field_accessor, None, computed_prop)
        };

        let field_stmt = if field.is_repeated() && !field.is_packed(ctx) && !field.is_map(ctx) {
            let field_name = normalize_name(field.name());
            
            // 获取基础类型名称
            let base_type = if field.is_message() {
                // 对于 message 类型，在 encoder 中不加 I 前缀
                let type_name = field.type_name();
                let raw_type_name = &type_name[type_name.rfind('.').map(|i| i + 1).unwrap_or(0)..];
                raw_type_name.to_string().into()
            } else if field.is_enum() {
                // 对于 enum 类型，使用 enum 类型名，保持原始大小写
                let type_name = field.type_name();
                let raw_type_name = &type_name[type_name.rfind('.').map(|i| i + 1).unwrap_or(0)..];
                raw_type_name.to_string().into()
            } else {
                // 对于基础类型，使用对应的 TypeScript 类型
                match field.type_() {
                    Type::TYPE_STRING => "string".into(),
                    Type::TYPE_BOOL => "boolean".into(),
                    Type::TYPE_INT64 | Type::TYPE_UINT64 | Type::TYPE_SINT64 | 
                    Type::TYPE_FIXED64 | Type::TYPE_SFIXED64 => "bigint".into(),
                    Type::TYPE_BYTES => "Uint8Array".into(),
                    _ => "number".into(), // 其他数值类型
                }
            };
        
            // 构建 Array<string> 类型 (替代 string[])
            let array_type = TsType::TsTypeRef(TsTypeRef {
                span: DUMMY_SP,
                type_name: TsEntityName::Ident(Ident::new("Array".into(), DUMMY_SP)),
                type_params: Some(Box::new(TsTypeParamInstantiation {
                    span: DUMMY_SP,
                    params: vec![Box::new(TsType::TsTypeRef(TsTypeRef {
                        span: DUMMY_SP,
                        type_name: TsEntityName::Ident(Ident::new(base_type, DUMMY_SP)),
                        type_params: None,
                    }))],
                })),
            });
        
            // 变量声明部分
            let var_decl = Stmt::Decl(Decl::Var(Box::new(VarDecl {
                span: DUMMY_SP,
                kind: VarDeclKind::Let,
                decls: vec![VarDeclarator {
                    span: DUMMY_SP,
                    name: Pat::Ident(BindingIdent {
                        id: Ident::new(field_name.clone().into(), DUMMY_SP),
                        type_ann: None,
                    }),
                    init: Some(Box::new(Expr::TsAs(TsAsExpr {
                        span: DUMMY_SP,
                        expr: Box::new(host_field_accessor(host_expr.clone(), field, has_computed_prop)),
                        type_ann: Box::new(array_type),
                    }))),
                    definite: false,
                }],
                declare: false,
            })));

        
            // Create the writer expression that will go inside for loop
            let field_header_value = field.field_header().value();
            let writer_expr = if field.is_message() {
                // For message types, use MessageType.encode(tag, $writer.uint32(X).fork()).ldelim()
                let type_name = field.type_name();
                let raw_type_name = &type_name[type_name.rfind('.').map(|i| i + 1).unwrap_or(0)..];
                
                let id_write_expr = Expr::Call(CallExpr {
                    span: DUMMY_SP,
                    callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                        span: DUMMY_SP,
                        obj: Box::new(Expr::Ident(Ident::new("$writer".into(), DUMMY_SP))),
                        prop: MemberProp::Ident(Ident::new("uint32".into(), DUMMY_SP)),
                    }))),
                    args: vec![ExprOrSpread {
                        spread: None,
                        expr: Box::new(Expr::Lit(Lit::Num(Number {
                            span: DUMMY_SP,
                            value: field_header_value as f64,
                            raw: None,
                        }))),
                    }],
                    type_args: None,
                });
                
                let writer_fork_expr = Expr::Call(CallExpr {
                    span: DUMMY_SP,
                    callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                        span: DUMMY_SP,
                        obj: Box::new(id_write_expr),
                        prop: MemberProp::Ident(Ident::new("fork".into(), DUMMY_SP)),
                    }))),
                    args: vec![],
                    type_args: None,
                });
                
                let field_write_expr = Expr::Call(CallExpr {
                    span: DUMMY_SP,
                    callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                        span: DUMMY_SP,
                        obj: Box::new(Expr::Member(MemberExpr {
                            span: DUMMY_SP,
                            obj: Box::new(Expr::Member(MemberExpr {
                                span: DUMMY_SP,
                                obj: Box::new(Expr::Ident(Ident::new(raw_type_name.into(), DUMMY_SP))),
                                prop: MemberProp::Ident(Ident::new("$meta".into(), DUMMY_SP)),
                            })),
                            prop: MemberProp::Ident(Ident::new("encoder".into(), DUMMY_SP)),
                        })),
                        prop: MemberProp::Ident(Ident::new("encode".into(), DUMMY_SP)),
                    }))),
                    args: vec![
                        ExprOrSpread {
                            spread: None,
                            expr: Box::new(Expr::Ident(Ident::new("tag".into(), DUMMY_SP))),
                        },
                        ExprOrSpread {
                            spread: None,
                            expr: Box::new(writer_fork_expr),
                        },
                    ],
                    type_args: None,
                });
                
                Expr::Call(CallExpr {
                    span: DUMMY_SP,
                    callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                        span: DUMMY_SP,
                        obj: Box::new(field_write_expr),
                        prop: MemberProp::Ident(Ident::new("ldelim".into(), DUMMY_SP)),
                    }))),
                    args: vec![],
                    type_args: None,
                })
            } else {
                // For primitive types, use the original logic
                let method_name = self.encoder_method_name(field);
                Expr::Call(CallExpr {
                    span: DUMMY_SP,
                    callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                        span: DUMMY_SP,
                        obj: Box::new(Expr::Member(MemberExpr {
                            span: DUMMY_SP,
                            obj: Box::new(Expr::Ident(Ident::new("$writer".into(), DUMMY_SP))),
                            prop: MemberProp::Ident(Ident::new(format!("uint32({})", field_header_value).into(), DUMMY_SP)),
                        })),
                        prop: MemberProp::Ident(Ident::new(method_name.into(), DUMMY_SP)),
                    }))),
                    args: vec![ExprOrSpread {
                        spread: None,
                        expr: Box::new(Expr::Ident(Ident::new("tag".into(), DUMMY_SP))),
                    }],
                    type_args: None,
                })
            };
        
            // for loop
            let for_loop = Stmt::For(ForStmt {
                span: DUMMY_SP,
                init: Some(VarDeclOrExpr::VarDecl(Box::new(VarDecl {
                    span: DUMMY_SP,
                    kind: VarDeclKind::Let,
                    declare: false,
                    decls: vec![VarDeclarator {
                        span: DUMMY_SP,
                        name: Pat::Ident(BindingIdent {
                            id: Ident::new("i".into(), DUMMY_SP),
                            type_ann: None,
                        }),
                        init: Some(Box::new(Expr::Lit(Lit::Num(Number {
                            span: DUMMY_SP,
                            value: 0.0,
                            raw: None,
                        })))),
                        definite: false,
                    }],
                }))),
                test: Some(Box::new(Expr::Bin(BinExpr {
                    span: DUMMY_SP,
                    left: Box::new(Expr::Ident(Ident::new("i".into(), DUMMY_SP))),
                    op: BinaryOp::Lt,
                    right: Box::new(Expr::Member(MemberExpr {
                        span: DUMMY_SP,
                        obj: Box::new(Expr::Ident(Ident::new(field_name.clone().into(), DUMMY_SP))),
                        prop: MemberProp::Ident(Ident::new("length".into(), DUMMY_SP)),
                    })),
                }))),
                update: Some(Box::new(Expr::Update(UpdateExpr {
                    span: DUMMY_SP,
                    op: UpdateOp::PlusPlus,
                    prefix: false,
                    arg: Box::new(Expr::Ident(Ident::new("i".into(), DUMMY_SP))),
                }))),
                body: Box::new(Stmt::Block(BlockStmt {
                    span: DUMMY_SP,
                    stmts: vec![
                        Stmt::Decl(Decl::Var(Box::new(VarDecl {
                            span: DUMMY_SP,
                            kind: VarDeclKind::Const,
                            declare: false,
                            decls: vec![VarDeclarator {
                                span: DUMMY_SP,
                                name: Pat::Ident(BindingIdent {
                                    id: Ident::new("tag".into(), DUMMY_SP),
                                    type_ann: None,
                                }),
                                init: Some(Box::new(Expr::Member(MemberExpr {
                                    span: DUMMY_SP,
                                    obj: Box::new(Expr::Ident(Ident::new(field_name.into(), DUMMY_SP))),
                                    prop: MemberProp::Computed(ComputedPropName {
                                        span: DUMMY_SP,
                                        expr: Box::new(Expr::Ident(Ident::new("i".into(), DUMMY_SP))),
                                    }),
                                }))),
                                definite: false,
                            }],
                        }))),
                        Stmt::Expr(ExprStmt {
                            span: DUMMY_SP,
                            expr: Box::new(writer_expr),
                        }),
                    ],
                })),
            });
        
            // Combine both statements
            Stmt::Block(BlockStmt {
                span: DUMMY_SP,
                stmts: vec![var_decl, for_loop],
            })
        } else {
            field_stmt
        };
        Some(field_stmt)
    }
    

    pub(super) fn serialize_setup_writer(&self, ctx: &mut Context) -> Stmt {
        let writer = ctx.get_import_from(Self::RUNTIME_PACKAGE, Self::PB_WRITER_NAME);
        let call = Expr::Member(MemberExpr {
            span: DUMMY_SP,
            obj: Box::new(writer.into()),
            prop: MemberProp::Ident(quote_ident!("create")),
        });
        let w = Expr::Ident(quote_ident!("$w"));
        let writer_decl_init = crate::bin_expr!(
            w,
            crate::call_expr!(call),
            swc_ecma_ast::BinaryOp::NullishCoalescing
        );
        
        Stmt::Decl(Decl::Var(Box::new(VarDecl {
            span: DUMMY_SP,
            kind: VarDeclKind::Const,
            declare: false,
            decls: vec![VarDeclarator {
                span: DUMMY_SP,
                name: Pat::Ident(BindingIdent {
                    id: quote_ident!("$writer"),
                    type_ann: Some(Box::new(TsTypeAnn {
                        span: DUMMY_SP,
                        type_ann: Box::new(TsType::TsTypeRef(TsTypeRef {
                            span: DUMMY_SP,
                            type_name: TsEntityName::Ident(quote_ident!("Writer")),
                            type_params: None,
                        })),
                    })),
                }),
                init: Some(Box::new(writer_decl_init)),
                definite: false,
            }],
        })))
    }


    pub fn serialize_oneof_field_stmt(
        &self,
        ctx: &mut Context,
        host_expr: Expr,
        oneof: &OneofDescriptorProto,
        fields: &[descriptor::FieldDescriptorProto],
        descriptor: &descriptor::DescriptorProto,
    ) -> Stmt {
        
        //获取联合类型
        let union_class_name = self.oneof_type_name(oneof, PropPos::Interface);
        // 生成 let oneOfParam: UnionType = $req.oneofName as UnionType
        let oneof_field_name = normalize_name(oneof.name());
        let identity_decl = Stmt::Decl(Decl::Var(Box::new(VarDecl {
            span: DUMMY_SP,
            kind: VarDeclKind::Let,
            decls: vec![VarDeclarator {
                span: DUMMY_SP,
                name: Pat::Ident(BindingIdent {
                    id: Ident::new("oneOfParam".into(), DUMMY_SP),
                    type_ann: Some(Box::new(TsTypeAnn {
                        span: DUMMY_SP,
                        type_ann: Box::new(TsType::TsTypeRef(TsTypeRef {
                            span: DUMMY_SP,
                            type_name: TsEntityName::Ident(union_class_name.clone()),
                            type_params: None,
                        })),
                    })),
                }),
                init: Some(Box::new(Expr::TsAs(TsAsExpr {
                    span: DUMMY_SP,
                    expr: Box::new(Expr::Member(MemberExpr {
                        span: DUMMY_SP,
                        obj: Box::new(Expr::Ident(Ident::new("$req".into(), DUMMY_SP))),
                        prop: MemberProp::Ident(Ident::new(oneof_field_name.as_str().into(), DUMMY_SP)),
                    })),
                    type_ann: Box::new(TsType::TsTypeRef(TsTypeRef {
                        span: DUMMY_SP,
                        type_name: TsEntityName::Ident(union_class_name.clone()),
                        type_params: None,
                    })),
                }))),
                definite: false,
            }],
            declare: false,
        })));
    
        // 生成 let kind: string = identityParam.$oneofKind
        let kind_decl = Stmt::Decl(Decl::Var(Box::new(VarDecl {
            span: DUMMY_SP,
            kind: VarDeclKind::Let,
            decls: vec![VarDeclarator {
                span: DUMMY_SP,
                name: Pat::Ident(BindingIdent {
                    id: Ident::new("kind".into(), DUMMY_SP),
                    type_ann: Some(Box::new(TsTypeAnn {
                        span: DUMMY_SP,
                        type_ann: Box::new(TsType::TsKeywordType(TsKeywordType {
                            span: DUMMY_SP,
                            kind: TsKeywordTypeKind::TsStringKeyword,
                        })),
                    })),
                }),
                init: Some(Box::new(Expr::Member(MemberExpr {
                    span: DUMMY_SP,
                    obj: Box::new(Expr::Ident(Ident::new("oneOfParam".into(), DUMMY_SP))),
                    prop: MemberProp::Ident(Ident::new("$oneofKind".into(), DUMMY_SP)),
                }))),
                definite: false,
            }],
            declare: false,
        })));
    
        // 生成 switch 语句的各个 case
        let mut cases = vec![];
        for field in fields {
            let type_name = self.oneof_variant_type_name(oneof, field, PropPos::Interface);
            let field_name = normalize_name(field.name());

            let var_name = format!("{}Identity", field_name.clone());
            let field_expr = Expr::Ident(Ident {
                span: DUMMY_SP,       // 使用默认的源码位置
                sym: var_name.clone().into(),  // 将字符串转换为标识符名称
                optional: false,       // 不是可选标识符(如 foo?.bar)
            });
            // 生成 let varName: Type = identityParam as Type
            let var_decl = Stmt::Decl(Decl::Var(Box::new(VarDecl {
                span: DUMMY_SP,
                kind: VarDeclKind::Let,
                decls: vec![VarDeclarator {
                    span: DUMMY_SP,
                    name: Pat::Ident(BindingIdent {
                        id: Ident::new(var_name.clone().into(), DUMMY_SP),
                        type_ann: Some(Box::new(TsTypeAnn {
                            span: DUMMY_SP,
                            type_ann: Box::new(TsType::TsTypeRef(TsTypeRef {
                                span: DUMMY_SP,
                                type_name: TsEntityName::Ident(type_name.clone()),
                                type_params: None,
                            })),
                        })),
                    }),
                    init: Some(Box::new(Expr::TsAs(TsAsExpr {
                        span: DUMMY_SP,
                        expr: Box::new(Expr::Ident(Ident::new("oneOfParam".into(), DUMMY_SP))),
                        type_ann: Box::new(TsType::TsTypeRef(TsTypeRef {
                            span: DUMMY_SP,
                            type_name: TsEntityName::Ident(type_name.clone()),
                            type_params: None,
                        })),
                    }))),
                    definite: false,
                }],
                declare: false,
            })));
    
            let write_expr = if field.is_message() {
                self.serialize_message_field_stmt(
                    ctx,
                    field_expr.clone(),
                    field,
                    host_field_accessor,
                    Some(false),
                )
            } else {
                self.serialize_oneof_primitive_field_stmt(
                    ctx,
                    field_expr.clone(),
                    field,
                    host_field_accessor,
                    None,
                    Some(false),
                )
            };
       
            let write_stmt = Stmt::If(IfStmt {
                span: DUMMY_SP,
                test: Box::new(Expr::Member(MemberExpr {
                    span: DUMMY_SP,
                    obj: Box::new(Expr::Ident(Ident::new(var_name.clone().into(), DUMMY_SP))),
                    prop: MemberProp::Ident(Ident::new(field_name.clone().into(), DUMMY_SP)),
                })),
                cons: Box::new(Stmt::Block(BlockStmt {
                    span: DUMMY_SP,
                    stmts: vec![write_expr],
                })),
                alt: None,
            });
    
            cases.push(SwitchCase {
                span: DUMMY_SP,
                test: Some(Box::new(Expr::Lit(Lit::Str(Str {
                    span: DUMMY_SP,
                    value: field_name.clone().into(),
                    raw: None,
                })))),
                cons: vec![var_decl, write_stmt, Stmt::Break(BreakStmt {
                    span: DUMMY_SP,
                    label: None,
                })],
            });
        }
    
        // 组合完整的 switch 语句
        let switch_stmt = Stmt::Switch(SwitchStmt {
            span: DUMMY_SP,
            discriminant: Box::new(Expr::Ident(Ident::new("kind".into(), DUMMY_SP))),
            cases,
        });
    
        // 返回组合后的语句块
        Stmt::Block(BlockStmt {
            span: DUMMY_SP,
            stmts: vec![identity_decl, kind_decl, switch_stmt],
        })
    }
    
    pub fn serialize_message_field_stmt(
        &self,
        ctx: &mut Context,
        host: Expr,
        field: &descriptor::FieldDescriptorProto,
        field_accessor: FieldAccessor,
        computed_prop: Option<bool>,
    ) -> Stmt {
        let has_computed_prop = computed_prop.unwrap_or(field.has_computed_prop());
        let access_expr = field_accessor(host, field, has_computed_prop);
         // If we need a type assertion, we'll wrap the expression in a TSAsExpr
        let access_expr = if !field.type_name().is_empty() {
            let type_name = ctx.lazy_type_ref(field.type_name());
            Expr::TsAs(swc_ecma_ast::TsAsExpr {
                expr: Box::new(access_expr),
                type_ann: Box::new(TsType::TsTypeRef(TsTypeRef {
                    span: Default::default(),
                    type_name: TsEntityName::Ident(type_name),
                    type_params: None,
                })),
                span: Default::default(),
            })
        } else {
            access_expr
        };
        let full_name = ctx.lazy_type_ref(field.type_name());
        // $w.uint32(/* (id << 3) |  wireType */)
        let id_write_expr = crate::call_expr!(
            crate::member_expr!("$writer", "uint32"),
            vec![crate::expr_or_spread!(
                crate::lit_num!(field.field_header().value()).into()
            )]
        );
        let writer_fork_expr = crate::call_expr!(crate::member_expr_bare!(id_write_expr, "fork"));
        let meta_member = crate::member_expr!(full_name, "$meta");
        let encoder_member = crate::member_expr_bare!(meta_member, "encoder");
        let field_write_expr = crate::call_expr!(
            crate::member_expr_bare!(encoder_member, "encode"),
            vec![
                crate::expr_or_spread!(access_expr),
                crate::expr_or_spread!(writer_fork_expr)
            ]
        );
        // package.XXX.encode(req.field_name, $w.uint32(/* */).fork()).ldelim();
        crate::expr_stmt!(crate::call_expr!(crate::member_expr_bare!(
            field_write_expr,
            "ldelim"
        )))
    }

    pub fn serialize_map_field_stmt(
        &self,
        ctx: &mut Context,
        host: Expr,
        field: &descriptor::FieldDescriptorProto,
    ) -> Stmt {
        let descriptor = ctx
            .get_map_type(field.type_name())
            .unwrap_or_else(|| panic!("cannot find the map type {}", field.type_name()));
    
        let field_name = normalize_name(field.name());
        let record_ident = format!("{}Record", field_name);
        let record_ident = quote_ident!(record_ident);
        let entry_ident = quote_ident!(field_name);
    
        // 生成 if 语句块
        let if_block = BlockStmt {
            span: DUMMY_SP,
            stmts: vec![
                // let scoresedRecord = ($req.scoresed as Record<string, number>)
                Stmt::Decl(Decl::Var(Box::new(VarDecl {
                    span: DUMMY_SP,
                    kind: VarDeclKind::Let,
                    declare: false,
                    decls: vec![VarDeclarator {
                        span: DUMMY_SP,
                        name: Pat::Ident(record_ident.clone().into()),
                        init: Some(Box::new(Expr::Paren(ParenExpr {
                            span: DUMMY_SP,
                            expr: Box::new(Expr::TsAs(TsAsExpr {
                                span: DUMMY_SP,
                                expr: Box::new(Expr::Paren(ParenExpr {
                                    span: DUMMY_SP,
                                    expr: Box::new(Expr::Member(MemberExpr {
                                        span: DUMMY_SP,
                                        obj: Box::new(host.clone()),
                                        prop: MemberProp::Ident(entry_ident.clone()),
                                    })),
                                })),
                                type_ann: Box::new(TsType::TsTypeRef(TsTypeRef {
                                    span: DUMMY_SP,
                                    type_name: TsEntityName::Ident(Ident::new("Record".into(), DUMMY_SP)),
                                    type_params: Some(Box::new(TsTypeParamInstantiation {
                                        span: DUMMY_SP,
                                        params: vec![
                                            Box::new(TsType::TsKeywordType(TsKeywordType {
                                                span: DUMMY_SP,
                                                kind: TsKeywordTypeKind::TsStringKeyword,
                                            })),
                                            Box::new(TsType::TsKeywordType(TsKeywordType {
                                                span: DUMMY_SP,
                                                kind: TsKeywordTypeKind::TsNumberKeyword,
                                            })),
                                        ],
                                    })),
                                })),
                            })),
                        }))),
                        definite: false,
                    }],
                }))),
                // for loop to replace forEach
                Stmt::Block(BlockStmt {
                    span: DUMMY_SP,
                    stmts: vec![
                        // const keys = Object.keys(record)
                        Stmt::Decl(Decl::Var(Box::new(VarDecl {
                            span: DUMMY_SP,
                            kind: VarDeclKind::Const,
                            declare: false,
                            decls: vec![VarDeclarator {
                                span: DUMMY_SP,
                                name: Pat::Ident(quote_ident!("keys").into()),
                                init: Some(Box::new(Expr::Call(CallExpr {
                                    span: DUMMY_SP,
                                    callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                                        span: DUMMY_SP,
                                        obj: Box::new(Expr::Ident(quote_ident!("Object"))),
                                        prop: MemberProp::Ident(quote_ident!("keys")),
                                    }))),
                                    args: vec![ExprOrSpread {
                                        spread: None,
                                        expr: Box::new(Expr::Ident(record_ident.clone())),
                                    }],
                                    type_args: None,
                                }))),
                                definite: false,
                            }],
                        }))),
                        // for loop
                        Stmt::For(ForStmt {
                            span: DUMMY_SP,
                            init: Some(VarDeclOrExpr::VarDecl(Box::new(VarDecl {
                                span: DUMMY_SP,
                                kind: VarDeclKind::Let,
                                declare: false,
                                decls: vec![VarDeclarator {
                                    span: DUMMY_SP,
                                    name: Pat::Ident(BindingIdent {
                                        id: quote_ident!("i"),
                                        type_ann: None,
                                    }),
                                    init: Some(Box::new(Expr::Lit(Lit::Num(Number {
                                        span: DUMMY_SP,
                                        value: 0.0,
                                        raw: None,
                                    })))),
                                    definite: false,
                                }],
                            }))),
                            test: Some(Box::new(Expr::Bin(BinExpr {
                                span: DUMMY_SP,
                                left: Box::new(Expr::Ident(quote_ident!("i"))),
                                op: BinaryOp::Lt,
                                right: Box::new(Expr::Member(MemberExpr {
                                    span: DUMMY_SP,
                                    obj: Box::new(Expr::Ident(quote_ident!("keys"))),
                                    prop: MemberProp::Ident(quote_ident!("length")),
                                })),
                            }))),
                            update: Some(Box::new(Expr::Update(UpdateExpr {
                                span: DUMMY_SP,
                                op: UpdateOp::PlusPlus,
                                prefix: false,
                                arg: Box::new(Expr::Ident(quote_ident!("i"))),
                            }))),
                            body: Box::new(Stmt::Block(BlockStmt {
                                span: DUMMY_SP,
                                stmts: vec![
                                    // const key = keys[i]
                                    Stmt::Decl(Decl::Var(Box::new(VarDecl {
                                        span: DUMMY_SP,
                                        kind: VarDeclKind::Const,
                                        declare: false,
                                        decls: vec![VarDeclarator {
                                            span: DUMMY_SP,
                                            name: Pat::Ident(quote_ident!("key").into()),
                                            init: Some(Box::new(Expr::Member(MemberExpr {
                                                span: DUMMY_SP,
                                                obj: Box::new(Expr::Ident(quote_ident!("keys"))),
                                                prop: MemberProp::Computed(ComputedPropName {
                                                    span: DUMMY_SP,
                                                    expr: Box::new(Expr::Ident(quote_ident!("i"))),
                                                }),
                                            }))),
                                            definite: false,
                                        }],
                                    }))),
                                    // ($writer.uint32(58)).fork()
                                    Stmt::Expr(ExprStmt {
                                        span: DUMMY_SP,
                                        expr: Box::new(Expr::Call(CallExpr {
                                            span: DUMMY_SP,
                                            callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                                                span: DUMMY_SP,
                                                obj: Box::new(Expr::Paren(ParenExpr {
                                                    span: DUMMY_SP,
                                                    expr: Box::new(Expr::Call(CallExpr {
                                                        span: DUMMY_SP,
                                                        callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                                                            span: DUMMY_SP,
                                                            obj: Box::new(Expr::Ident(quote_ident!("$writer"))),
                                                            prop: MemberProp::Ident(quote_ident!("uint32")),
                                                        }))),
                                                        args: vec![ExprOrSpread {
                                                            spread: None,
                                                            expr: Box::new(Expr::Lit(Lit::Num(Number {
                                                                span: DUMMY_SP,
                                                                value: ((field.number() << 3) | 2) as f64,
                                                                raw: None,
                                                            }))),
                                                        }],
                                                        type_args: None,
                                                    })),
                                                })),
                                                prop: MemberProp::Ident(quote_ident!("fork")),
                                            }))),
                                            args: vec![],
                                            type_args: None,
                                        })),
                                    }),
                                    // if (scoresedRecord[key]) {...}
                                    Stmt::If(IfStmt {
                                        span: DUMMY_SP,
                                        test: Box::new(Expr::Paren(ParenExpr {
                                            span: DUMMY_SP,
                                            expr: Box::new(Expr::Member(MemberExpr {
                                                span: DUMMY_SP,
                                                obj: Box::new(Expr::Ident(record_ident.clone())),
                                                prop: MemberProp::Computed(ComputedPropName {
                                                    span: DUMMY_SP,
                                                    expr: Box::new(Expr::Ident(quote_ident!("key"))),
                                                }),
                                            })),
                                        })),
                                        cons: Box::new(Stmt::Block(BlockStmt {
                                            span: DUMMY_SP,
                                            stmts: vec![
                                                // const value = (scoresedRecord[key] as number)
                                                Stmt::Decl(Decl::Var(Box::new(VarDecl {
                                                    span: DUMMY_SP,
                                                    kind: VarDeclKind::Const,
                                                    decls: vec![VarDeclarator {
                                                        span: DUMMY_SP,
                                                        name: Pat::Ident(quote_ident!("value").into()),
                                                        init: Some(Box::new(Expr::Paren(ParenExpr {
                                                            span: DUMMY_SP,
                                                            expr: Box::new(Expr::TsAs(TsAsExpr {
                                                                span: DUMMY_SP,
                                                                expr: Box::new(Expr::Paren(ParenExpr {
                                                                    span: DUMMY_SP,
                                                                    expr: Box::new(Expr::Member(MemberExpr {
                                                                        span: DUMMY_SP,
                                                                        obj: Box::new(Expr::Ident(record_ident.clone())),
                                                                        prop: MemberProp::Computed(ComputedPropName {
                                                                            span: DUMMY_SP,
                                                                            expr: Box::new(Expr::Ident(quote_ident!("key"))),
                                                                        }),
                                                                    })),
                                                                })),
                                                                type_ann: Box::new(TsType::TsKeywordType(TsKeywordType {
                                                                    span: DUMMY_SP,
                                                                    kind: TsKeywordTypeKind::TsNumberKeyword,
                                                                })),
                                                            })),
                                                        }))),
                                                        definite: false,
                                                    }],
                                                    declare: false,
                                                }))),
                                                // (($writer.uint32(10)).string_(key)
                                                Stmt::Expr(ExprStmt {
                                                    span: DUMMY_SP,
                                                    expr: Box::new(Expr::Call(CallExpr {
                                                        span: DUMMY_SP,
                                                        callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                                                            span: DUMMY_SP,
                                                            obj: Box::new(Expr::Paren(ParenExpr {
                                                                span: DUMMY_SP,
                                                                expr: Box::new(Expr::Call(CallExpr {
                                                                    span: DUMMY_SP,
                                                                    callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                                                                        span: DUMMY_SP,
                                                                        obj: Box::new(Expr::Ident(quote_ident!("$writer"))),
                                                                        prop: MemberProp::Ident(quote_ident!("uint32")),
                                                                    }))),
                                                                    args: vec![ExprOrSpread {
                                                                        spread: None,
                                                                        expr: Box::new(Expr::Lit(Lit::Num(Number {
                                                                            span: DUMMY_SP,
                                                                            value: 10.0,
                                                                            raw: None,
                                                                        }))),
                                                                    }],
                                                                    type_args: None,
                                                                })),
                                                            })),
                                                            prop: MemberProp::Ident(quote_ident!("string_")),
                                                        }))),
                                                        args: vec![ExprOrSpread {
                                                            spread: None,
                                                            expr: Box::new(Expr::Ident(quote_ident!("key"))),
                                                        }],
                                                        type_args: None,
                                                    })),
                                                }),
                                                // (($writer.uint32(16)).int32(value))
                                                Stmt::Expr(ExprStmt {
                                                    span: DUMMY_SP,
                                                    expr: Box::new(Expr::Call(CallExpr {
                                                        span: DUMMY_SP,
                                                        callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                                                            span: DUMMY_SP,
                                                            obj: Box::new(Expr::Paren(ParenExpr {
                                                                span: DUMMY_SP,
                                                                expr: Box::new(Expr::Call(CallExpr {
                                                                    span: DUMMY_SP,
                                                                    callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                                                                        span: DUMMY_SP,
                                                                        obj: Box::new(Expr::Ident(quote_ident!("$writer"))),
                                                                        prop: MemberProp::Ident(quote_ident!("uint32")),
                                                                    }))),
                                                                    args: vec![ExprOrSpread {
                                                                        spread: None,
                                                                        expr: Box::new(Expr::Lit(Lit::Num(Number {
                                                                            span: DUMMY_SP,
                                                                            value: 16.0,
                                                                            raw: None,
                                                                        }))),
                                                                    }],
                                                                    type_args: None,
                                                                })),
                                                            })),
                                                            prop: MemberProp::Ident(quote_ident!("int32")),
                                                        }))),
                                                        args: vec![ExprOrSpread {
                                                            spread: None,
                                                            expr: Box::new(Expr::Ident(quote_ident!("value"))),
                                                        }],
                                                        type_args: None,
                                                    })),
                                                }),
                                                // $writer.ldelim()
                                                Stmt::Expr(ExprStmt {
                                                    span: DUMMY_SP,
                                                    expr: Box::new(Expr::Call(CallExpr {
                                                        span: DUMMY_SP,
                                                        callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                                                            span: DUMMY_SP,
                                                            obj: Box::new(Expr::Ident(quote_ident!("$writer"))),
                                                            prop: MemberProp::Ident(quote_ident!("ldelim")),
                                                        }))),
                                                        args: vec![],
                                                        type_args: None,
                                                    })),
                                                }),
                                            ],
                                        })),
                                        alt: None,
                                    }),
                                ],
                            })),
                        }),
                    ],
                }),
            ],
        };
    
        // 生成完整的 if 语句
        Stmt::If(IfStmt {
            span: DUMMY_SP,
            test: Box::new(Expr::Member(MemberExpr {
                span: DUMMY_SP,
                obj: Box::new(host),
                prop: MemberProp::Ident(entry_ident),
            })),
            cons: Box::new(Stmt::Block(if_block)),
            alt: None,
        })
    }

pub fn serialize_primitive_field_stmt(
    &self,
    _ctx: &mut Context,
    host: Expr,
    field: &descriptor::FieldDescriptorProto,
    field_accessor: FieldAccessor,
    access_normalizer: Option<field::AccessNormalizerFn>,
    has_computed_prop: Option<bool>,
) -> Stmt {
    let has_computed_prop = has_computed_prop.unwrap_or(field.has_computed_prop());
    let access_expr = field_accessor(host, field, has_computed_prop);
    let access_expr_normalized = access_normalizer // Renamed to avoid conflict with test condition
        .map(|f| f(&access_expr))
        .unwrap_or_else(|| access_expr.clone());

    // 使用 pure_type_annotation 获取纯类型
    let typed_access_expr = if let Some(type_ann) = field.pure_type_annotation(_ctx) {
        Expr::TsAs(TsAsExpr {
            span: DUMMY_SP,
            expr: Box::new(access_expr_normalized.clone()), // Use normalized access_expr here
            type_ann: Box::new(*type_ann.type_ann),  // 解引用获取 TsType
        })
    } else {
        // 回退到原来的硬编码类型匹配
        match field.type_() {
            Type::TYPE_STRING => Expr::TsAs(TsAsExpr {
                span: DUMMY_SP,
                expr: Box::new(access_expr_normalized.clone()), // Use normalized access_expr here
                type_ann: Box::new(TsType::TsKeywordType(TsKeywordType {
                    span: DUMMY_SP,
                    kind: TsKeywordTypeKind::TsStringKeyword,
                })),
            }),
            // 根据需要为其他类型添加 TsAsExpr，或者保持原样
            _ => access_expr_normalized.clone(), // Use normalized access_expr here
        }
    };

    // $w.uint32(/* id + wireType */)
    let id_write_expr = Expr::Call(CallExpr {
        span: DUMMY_SP,
        callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
            span: DUMMY_SP,
            obj: Box::new(Expr::Ident(Ident::new("$writer".into(), DUMMY_SP))),
            prop: MemberProp::Ident(Ident::new("uint32".into(), DUMMY_SP)),
        }))),
        args: vec![ExprOrSpread {
            spread: None,
            expr: Box::new(Expr::Lit(Lit::Num(Number {
                span: DUMMY_SP,
                value: field.field_header().value() as f64,
                raw: None,
            }))),
        }],
        type_args: None,
    });

    // 获取编码器方法名（已包含下划线处理）
    let method_name_str = self.encoder_method_name(field);

    let if_stmt = Stmt::If(IfStmt {
        span: DUMMY_SP,
        test: Box::new(access_expr), // The condition for `if` should use the original access_expr (before normalization for TsAs)
        cons: Box::new(Stmt::Block(BlockStmt {
            span: DUMMY_SP,
            stmts: vec![
                Stmt::Expr(ExprStmt {
                    span: DUMMY_SP,
                    expr: Box::new(Expr::Call(CallExpr {
                        span: DUMMY_SP,
                        callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                            span: DUMMY_SP,
                            obj: Box::new(id_write_expr),
                            prop: MemberProp::Ident(Ident::new(
                                method_name_str.into(), // 使用修改后的方法名
                                DUMMY_SP
                            )),
                        }))),
                        args: vec![ExprOrSpread {
                            spread: None,
                            expr: Box::new(typed_access_expr), // 使用可能经过类型断言的表达式
                        }],
                        type_args: None,
                    })),
                })
            ],
        })),
        alt: None,
    });
    if_stmt
}


    pub fn serialize_oneof_primitive_field_stmt(
        &self,
        _ctx: &mut Context,
        host: Expr,
        field: &descriptor::FieldDescriptorProto,
        field_accessor: FieldAccessor,
        access_normalizer: Option<field::AccessNormalizerFn>,
        has_computed_prop: Option<bool>,
    ) -> Stmt {
        let has_computed_prop = has_computed_prop.unwrap_or(field.has_computed_prop());
        eprintln!("[DEBUG] field_type has_computed_prop >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}", has_computed_prop);
        let access_expr_intermediate = field_accessor(host.clone(), field, has_computed_prop);
        eprintln!("[DEBUG] field_type host >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}", host);
        eprintln!("[DEBUG] field_type field >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}", field);
        eprintln!("[DEBUG] field_type access_expr111 >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}", access_expr_intermediate);
        let access_expr = access_normalizer
            .map(|f| f(&access_expr_intermediate))
            .unwrap_or(access_expr_intermediate);
        eprintln!("[DEBUG] field_type access_expr222 >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}", access_expr);

        // $w.uint32(/* id + wireType */)
        let id_write_expr = crate::call_expr!(
            crate::member_expr!("$writer", "uint32"),
            vec![crate::expr_or_spread!(
                crate::lit_num!(field.field_header().value()).into() // .into() assuming lit_num! returns Lit, and ExprOrSpread expects Expr
            )]
        );
        eprintln!("[DEBUG] field_type id_write_expr >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}", id_write_expr);

        // 获取编码器方法名（已包含下划线处理）
        let method_name_str = self.encoder_method_name(field);

        // 这个 eprintln 仍然使用原始方法名进行调试打印，根据您的原始代码保留
        eprintln!("[DEBUG] field_type id_write_expr2222 >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}", crate::expr_stmt!(crate::call_expr!(
            crate::member_expr_bare!(id_write_expr.clone(), self.codec_fn_name(field)), // 注意：这里是原始方法名
            vec![crate::expr_or_spread!(access_expr.clone())]
        )));

        // $w.uint32(/* */).xxx_(/* */) 调用，注意这里 xxx_() 是可能被修改后的方法名
        crate::expr_stmt!(crate::call_expr!(
            crate::member_expr_bare!(id_write_expr, method_name_str), // 使用修改后的方法名
            vec![crate::expr_or_spread!(access_expr)]
        ))
    }
}